home *** CD-ROM | disk | FTP | other *** search
/ Utilities Professional 1-1500 / Utilities Professional 1-1500 (1994)(WPD)[!].iso / 12511500 / var1273.dms / var1273.adf / AmiCDROM / iso9660.c < prev    next >
C/C++ Source or Header  |  1992-09-02  |  18KB  |  763 lines

  1. /* iso9660.c:
  2.  *
  3.  * Support for the ISO-9660 filing system.
  4.  *
  5.  * ----------------------------------------------------------------------
  6.  * This code is (C) Copyright 1993 by Frank Munkert.
  7.  * All rights reserved.
  8.  * This software may be freely distributed and redistributed for
  9.  * non-commercial purposes, provided this notice is included.
  10.  * ----------------------------------------------------------------------
  11.  * History:
  12.  * 
  13.  * 02-Dec-93   fmu   Bugfix: a logical block of a file extent must not
  14.  *                   necessarily start at a logical sector border.
  15.  * 29-Nov-93   fmu   - New function Iso_Block_Size().
  16.  *                   - Support for variable logical block sizes.
  17.  * 15-Nov-93   fmu   Uses_High_Sierra_Protocol added.
  18.  * 13-Nov-93   fmu   Bad iso_errno return value in Iso_Open_Obj_In_Directory
  19.  *                   corrected.
  20.  * 12-Oct-93   fmu   Adapted to new VOLUME and CDROM_OBJ structures.
  21.  * 24-Sep-93   fmu   Two further bugs in Seek_Position fixed.
  22.  * 16-Sep-93   fmu   Fixed bug in Seek_Position.
  23.  * 16-Sep-93   fmu   Bugfix: Top level object recognition in CDROM_Info
  24.  *                   had to be changed for Rock Ridge disks.
  25.  */
  26.  
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <ctype.h>
  30.  
  31. #include <exec/types.h>
  32. #include <exec/memory.h>
  33. #include <clib/exec_protos.h>
  34. #include <clib/utility_protos.h>
  35. #ifdef AZTEC_C
  36. #include <pragmas/exec_lib.h>
  37. #include <pragmas/utility_lib.h>
  38. #endif
  39. #ifdef LATTICE
  40. #include <pragmas/exec_pragmas.h>
  41. #include <pragmas/utility_pragmas.h>
  42. #endif
  43. #if defined(_DCC) && defined(REGISTERED)
  44. #include <pragmas/exec_pragmas.h>
  45. #include <pragmas/utility_pragmas.h>
  46. extern struct Library *SysBase;
  47. #endif
  48.  
  49. #include "cdrom.h"
  50. #include "iso9660.h"
  51. #include "rock.h"
  52.  
  53. extern struct Library *UtilityBase;
  54.  
  55. t_bool Iso_Is_Top_Level_Object (CDROM_OBJ *);
  56.  
  57. int iso_errno;
  58.  
  59. #define VOL(vol,tag) (((t_iso_vol_info *)(vol->vol_info))->tag)
  60. #define OBJ(obj,tag) (((t_iso_obj_info *)(obj->obj_info))->tag)
  61.  
  62. /* Check whether the given volume uses the ISO 9660 Protocol.
  63.  * The protocol is identified by the sequence
  64.  *            'C' 'D' '0' '0' '1'
  65.  * in the 2nd..6th byte of sector 16.
  66.  *
  67.  * Returns TRUE iff the ISO protocol is used; FALSE otherwise.
  68.  */
  69.  
  70. t_bool Uses_Iso_Protocol (CDROM *p_cdrom)
  71. {
  72.   if (!Read_Sector (p_cdrom, 16))
  73.     return FALSE;
  74.   
  75.   return strncmp ((char *) p_cdrom->buffer + 1, "CD001", 5) == 0;
  76. }
  77.  
  78. /* Check whether the given volume uses the High Sierra Protocol.
  79.  * The protocol is identified by the sequence
  80.  *            'C' 'D' 'R' 'O' 'M'
  81.  * in the 10th..14th byte of sector 16.
  82.  *
  83.  * Returns TRUE iff the High Sierra protocol is used; FALSE otherwise.
  84.  */
  85.  
  86. t_bool Uses_High_Sierra_Protocol (CDROM *p_cdrom)
  87. {
  88.   if (!Read_Sector (p_cdrom, 16))
  89.     return FALSE;
  90.   
  91.   return strncmp ((char *) p_cdrom->buffer + 9, "CDROM", 5) == 0;
  92. }
  93.  
  94. t_bool Iso_Init_Vol_Info (VOLUME *p_volume, int p_skip)
  95. {
  96.   long loc = 16;
  97.   extern t_handler g_iso_handler, g_rr_handler;
  98.  
  99.   if (p_volume->protocol == PRO_ISO)
  100.     p_volume->handler = &g_iso_handler;
  101.   else
  102.     p_volume->handler = &g_rr_handler;
  103.  
  104.   p_volume->vol_info = AllocMem (sizeof (t_iso_vol_info), MEMF_PUBLIC);
  105.   if (!p_volume->vol_info) {
  106.     iso_errno = ISOERR_NO_MEMORY;
  107.     return FALSE;
  108.   }
  109.  
  110.   for (;;) {
  111.     if (!Read_Sector (p_volume->cd, loc)) {
  112.       iso_errno = ISOERR_SCSI_ERROR;
  113.       FreeMem (p_volume->vol_info, sizeof (t_iso_vol_info));
  114.       return FALSE;
  115.     }
  116.  
  117.     if (p_volume->cd->buffer[0] == 1) {
  118.       memcpy (&VOL(p_volume,pvd), p_volume->cd->buffer, sizeof (prim_vol_desc));
  119.       break;
  120.     }
  121.     
  122.     if (p_volume->cd->buffer[0] == 255 || loc > 1000) {
  123.       iso_errno = ISOERR_NO_PVD;
  124.       FreeMem (p_volume->vol_info, sizeof (t_iso_vol_info));
  125.       return FALSE;
  126.     }
  127.     
  128.     loc++;
  129.   }
  130.   
  131.   VOL(p_volume,skip) = p_skip;
  132.  
  133.   switch (VOL(p_volume,pvd).block_size_m) {
  134.   case 512:
  135.     VOL(p_volume,blockshift) = 2;
  136.     break;
  137.   case 1024:
  138.     VOL(p_volume,blockshift) = 1;
  139.     break;
  140.   case 2048:
  141.   default:
  142.     VOL(p_volume,blockshift) = 0;
  143.     break;
  144.   }
  145.  
  146.   return TRUE;
  147. }
  148.  
  149. void Iso_Close_Vol_Info (VOLUME *p_volume)
  150. {
  151.   FreeMem (p_volume->vol_info, sizeof (t_iso_vol_info));
  152. }
  153.  
  154. CDROM_OBJ *Iso_Alloc_Obj (int p_length_of_dir_record)
  155. {
  156.   CDROM_OBJ *obj;
  157.  
  158.   obj = AllocMem (sizeof (CDROM_OBJ), MEMF_PUBLIC | MEMF_CLEAR);
  159.   if (!obj) {
  160.     iso_errno = ISOERR_NO_MEMORY;
  161.     return NULL;
  162.   }
  163.  
  164.   obj->obj_info = AllocMem (sizeof (t_iso_obj_info), MEMF_PUBLIC);
  165.   if (!obj->obj_info) {
  166.     FreeMem (obj, sizeof (CDROM_OBJ));
  167.     return NULL;
  168.   }
  169.  
  170.   OBJ(obj,dir) = AllocMem (p_length_of_dir_record, MEMF_PUBLIC);
  171.   if (!OBJ(obj,dir)) {
  172.     iso_errno = ISOERR_NO_MEMORY;
  173.     FreeMem (obj->obj_info, sizeof (t_iso_obj_info));
  174.     FreeMem (obj, sizeof (CDROM_OBJ));
  175.     return NULL;
  176.   }
  177.  
  178.   return obj;
  179. }
  180.  
  181. /* Get the "CDROM object" for the root directory of the volume.
  182.  */
  183.  
  184. CDROM_OBJ *Iso_Open_Top_Level_Directory (VOLUME *p_volume)
  185. {
  186.   CDROM_OBJ *obj;
  187.  
  188.   obj = Iso_Alloc_Obj (VOL(p_volume,pvd).root.length);
  189.   if (!obj)
  190.     return NULL;
  191.  
  192.   obj->directory_f = TRUE;
  193.   obj->volume = p_volume;
  194.   obj->pos = 0;
  195.   memcpy (OBJ(obj,dir), &VOL(p_volume,pvd).root, VOL(p_volume,pvd).root.length);
  196.  
  197.   return obj;
  198. }
  199.  
  200. /* Test on equality of directory names (ignoring case).
  201.  */
  202.  
  203. int Directory_Names_Equal (char *p_iso_name, int p_length, char *p_name)
  204. {
  205.   return Strncasecmp (p_iso_name, p_name, p_length) == 0 &&
  206.        p_name[p_length] == 0;
  207. }
  208.  
  209. /* Compare the name of the directory entry p_iso_name (with length p_length)
  210.  * with the C string p_name, and return 1 iff both strings are equal.
  211.  * NOTE: p_iso_name may be a file name (with version number) or a directory
  212.  *       name (without version number).
  213.  */
  214.  
  215. int Names_Equal (char *p_iso_name, int p_length, char *p_name)
  216. {
  217.   int pos;
  218.  
  219.   if (Strncasecmp (p_iso_name, p_name, p_length) == 0 &&
  220.       p_name[p_length] == 0)
  221.     return TRUE;
  222.   
  223.   /* compare without version number: */
  224.   
  225.   for (pos=p_length-1; pos>=0; pos--)
  226.     if (p_iso_name[pos] == ';')
  227.       break;
  228.  
  229.   if (pos>=0)
  230.     return (Strncasecmp (p_iso_name, p_name, pos) == 0 &&
  231.             p_name[pos] == 0);
  232.   else
  233.     return FALSE;
  234. }
  235.  
  236. /* Get a record from a directory.
  237.  * p_location is a LOGICAL BLOCK number.
  238.  */
  239.  
  240. directory_record *Get_Directory_Record (VOLUME *p_volume,
  241.                     unsigned long p_location,
  242.                     unsigned long p_offset)
  243. {
  244.   static unsigned char result[256];
  245.   int len;
  246.   int loc;
  247.   
  248.   loc = (p_location >> VOL(p_volume,blockshift)) + (p_offset >> 11);
  249.   if (!Read_Sector (p_volume->cd, loc)) {
  250.     iso_errno = ISOERR_SCSI_ERROR;
  251.     return NULL;
  252.   }
  253.  
  254.   len = p_volume->cd->buffer[p_offset & 2047];
  255.   if (len)
  256.     memcpy (result, p_volume->cd->buffer + (p_offset & 2047), len);
  257.   else
  258.     result[0] = 0;  /* mark as last record */
  259.   
  260.   return (directory_record *) result;
  261. }
  262.  
  263. /* Create a "CDROM object" for the directory which is located
  264.  * at sector p_location.
  265.  */
  266.  
  267. CDROM_OBJ *Iso_Create_Directory_Obj (VOLUME *p_volume, unsigned long p_location)
  268. {
  269.   directory_record *dir;
  270.   unsigned long loc;
  271.   int offset = 0;
  272.   CDROM_OBJ *obj;
  273.   unsigned long len;
  274.  
  275.   if (p_location == VOL(p_volume,pvd).root.extent_loc_m)
  276.     return Iso_Open_Top_Level_Directory (p_volume);
  277.  
  278.   dir = Get_Directory_Record (p_volume, p_location, 0);
  279.   if (!dir)
  280.     return NULL;
  281.   
  282.   dir = Get_Directory_Record (p_volume, p_location, dir->length);
  283.   if (!dir)
  284.     return NULL;
  285.   
  286.   loc = dir->extent_loc_m;
  287.   len = dir->data_length_m;
  288.   for (;;) {
  289.     if (offset >= len)
  290.       return NULL;
  291.     dir = Get_Directory_Record (p_volume, loc, offset);
  292.     if (!dir)
  293.       return NULL;
  294.     if (!dir->length) {
  295.       /* go to next logical sector: */
  296.       offset = (offset & 0xfffff800) + 2048;
  297.       continue;
  298.     }
  299.     if (dir->extent_loc_m == p_location)
  300.       break;
  301.     offset += dir->length;
  302.   }
  303.  
  304.   obj = Iso_Alloc_Obj (dir->length);
  305.   if (!obj)
  306.     return NULL;
  307.  
  308.   obj->directory_f = TRUE;
  309.   obj->volume = p_volume;
  310.   obj->pos = 0;
  311.   memcpy (OBJ(obj,dir), dir, dir->length);
  312.  
  313.   return obj;
  314. }
  315.  
  316.  
  317. /* Open the object with name p_name in the directory p_dir.
  318.  * p_name must not contain '/' or ':' characters.
  319.  */
  320.  
  321. CDROM_OBJ *Iso_Open_Obj_In_Directory (CDROM_OBJ *p_dir, char *p_name)
  322. {
  323.   unsigned long loc = OBJ(p_dir,dir)->extent_loc_m;
  324.   unsigned long len = OBJ(p_dir,dir)->data_length_m;
  325.   directory_record *dir;
  326.   int offset;
  327.   CDROM_OBJ *obj;
  328.  
  329.   /* skip first two entries: */
  330.  
  331.   dir = Get_Directory_Record (p_dir->volume, loc, 0);
  332.   if (!dir)
  333.     return NULL;
  334.   
  335.   offset = dir->length;
  336.   dir = Get_Directory_Record (p_dir->volume, loc, offset);
  337.   if (!dir)
  338.     return NULL;
  339.  
  340.   offset += dir->length;
  341.   for (;;) {
  342.     if (offset >= len) {
  343.       iso_errno = ISOERR_NOT_FOUND;
  344.       return NULL;
  345.     }
  346.     dir = Get_Directory_Record (p_dir->volume, loc, offset);
  347.     if (!dir)
  348.       return NULL;
  349.     if (!dir->length) {
  350.       /* go to next logical sector: */
  351.       offset = (offset & 0xfffff800) + 2048;
  352.       continue;
  353.     }
  354.     if (p_dir->volume->protocol == PRO_ROCK) {
  355.       char buf[256];
  356.       int len;
  357.  
  358.       if ((len = Get_RR_File_Name (p_dir->volume, dir, buf, sizeof (buf))) > 0 &&
  359.           Strncasecmp (buf, p_name, len) == 0 &&
  360.       p_name[len] == 0)
  361.     break;
  362.     }
  363.  
  364.     if (Names_Equal (dir->file_id, dir->file_id_length, p_name))
  365.       break;
  366.     offset += dir->length;
  367.   }
  368.  
  369.   obj = Iso_Alloc_Obj (dir->length);
  370.   if (!obj)
  371.     return NULL;
  372.  
  373.   obj->directory_f = (dir->flags & 2);
  374.   obj->volume = p_dir->volume;
  375.   obj->pos = 0;
  376.   memcpy (OBJ(obj,dir), dir, dir->length);
  377.  
  378.   return obj;
  379. }
  380.  
  381. /* Close a "CDROM object" and deallocate all associated resources.
  382.  */
  383.  
  384. void Iso_Close_Obj (CDROM_OBJ *p_object)
  385. {
  386.   FreeMem (OBJ(p_object,dir), OBJ(p_object,dir)->length);
  387.   FreeMem (p_object->obj_info, sizeof (t_iso_obj_info));
  388.   FreeMem (p_object, sizeof (CDROM_OBJ));
  389. }
  390.  
  391. /* Read bytes from a file.
  392.  */
  393.  
  394. int Iso_Read_From_File (CDROM_OBJ *p_file, char *p_buffer, int p_buffer_length)
  395. {
  396.   unsigned long loc;
  397.   int remain_block, remain_file, remain;
  398.   int len;
  399.   VOLUME *vol = p_file->volume;
  400.   CDROM *cd = vol->cd;
  401.   int buf_pos = 0;
  402.   int todo;
  403.   unsigned long last_loc, ext_loc;
  404.   short blockshift;
  405.   int offset;
  406.  
  407.   if (p_file->pos == OBJ(p_file,dir)->data_length_m)
  408.     /* at end of file: */
  409.     return 0;
  410.  
  411.   blockshift = VOL(vol,blockshift);
  412.   /*
  413.    * 'offset' is the offset of the first logical block of the file
  414.    * extent from the first logical (2048-byte-)sector.
  415.    */
  416.   if (blockshift)
  417.     offset = (((OBJ(p_file,dir)->extent_loc_m) & ((1<<blockshift)-1))
  418.               << (11-blockshift));
  419.   else
  420.     offset = 0;
  421.   /*
  422.    * 'ext_loc' is the first logical sector of the file extent.
  423.    * 'loc' is the first logical sector to be read.
  424.    * 'last_loc' is the last logical sector of the file extent.
  425.    */
  426.   ext_loc = OBJ(p_file,dir)->extent_loc_m >> blockshift;
  427.   loc = ext_loc + ((p_file->pos + offset) >> 11);
  428.   last_loc = ext_loc + ((OBJ(p_file,dir)->data_length_m + offset - 1) >> 11);
  429.   todo = p_buffer_length;
  430.  
  431.   offset += p_file->pos;
  432.   offset &= 2047;
  433.   remain_block = 2048 - offset;
  434.  
  435.   while (todo) {
  436.     if (!Read_Contiguous_Sectors (cd, loc, last_loc)) {
  437.       iso_errno = ISOERR_SCSI_ERROR;
  438.       return -1;
  439.     }
  440.  
  441.     remain_file = OBJ(p_file,dir)->data_length_m - p_file->pos;
  442.     /* 
  443.      * 'todo' is the number of bytes in p_buffer which haven't been filled yet.
  444.      * 'remain' is remaining number of bytes in cd->buffer.
  445.      */
  446.     remain = (remain_block < remain_file) ? remain_block : remain_file;
  447.     len = (todo < remain) ? todo : remain;
  448.     CopyMem ((APTR) (cd->buffer + offset), (APTR) (p_buffer + buf_pos), len);
  449.     buf_pos += len;
  450.     p_file->pos += len;
  451.     todo -= len;
  452.  
  453.     if (p_file->pos >= OBJ(p_file,dir)->data_length_m)
  454.       break;
  455.  
  456.     remain_block = 2048;
  457.     offset = 0;
  458.  
  459.     loc++;
  460.   }
  461.  
  462.   return buf_pos;
  463. }
  464.  
  465. t_ulong Extract_Date (directory_record *p_dir_record)
  466. {
  467.   struct ClockData ClockData;
  468.  
  469.   ClockData.sec   = p_dir_record->second;
  470.   ClockData.min      = p_dir_record->minute;
  471.   ClockData.hour  = p_dir_record->hour;
  472.   ClockData.mday  = p_dir_record->day;
  473.   ClockData.wday  = 0; /* is ignored by CheckDate() and Date2Amiga() */
  474.   ClockData.month = p_dir_record->month;
  475.   ClockData.year  = p_dir_record->year + 1900;
  476.  
  477.   if (CheckDate (&ClockData))
  478.     return Date2Amiga (&ClockData);
  479.   else
  480.     return 0;
  481. }
  482.  
  483. /* Return information on a "CDROM object."
  484.  */
  485.  
  486. int Iso_CDROM_Info (CDROM_OBJ *p_obj, CDROM_INFO *p_info)
  487. {
  488.   int len;
  489.  
  490.   if (Iso_Is_Top_Level_Object (p_obj)) {
  491.     p_info->name_length = 1;
  492.     p_info->name[0] = ':';
  493.     p_info->directory_f = TRUE;
  494.     p_info->file_length = 0;
  495.     p_info->date = Volume_Creation_Date (p_obj->volume);
  496.   } else {
  497.     if (p_obj->volume->protocol == PRO_ROCK &&
  498.         (len = Get_RR_File_Name (p_obj->volume, OBJ(p_obj,dir),
  499.                        p_info->name, sizeof (p_info->name))) > 0) {
  500.       p_info->name_length = len;
  501.     } else {
  502.       p_info->name_length = OBJ(p_obj,dir)->file_id_length;
  503.       memcpy (p_info->name, OBJ(p_obj,dir)->file_id, p_info->name_length);
  504.     }
  505.     p_info->directory_f = p_obj->directory_f;
  506.     p_info->file_length = OBJ(p_obj,dir)->data_length_m;
  507.     p_info->date = Extract_Date (OBJ(p_obj,dir));
  508.   }
  509.  
  510.   return 1;
  511. }
  512.  
  513. /* Browse all entries in a directory.
  514.  */
  515.  
  516. int Iso_Examine_Next (CDROM_OBJ *p_dir, CDROM_INFO *p_info,
  517.               unsigned long *p_offset)
  518. {
  519.   unsigned long offset;
  520.   directory_record *rec;
  521.   int len;
  522.  
  523.   if (!p_dir->directory_f) {
  524.     iso_errno = ISOERR_BAD_ARGUMENTS;
  525.     return 0;
  526.   }
  527.  
  528.   if (*p_offset == 0) {
  529.     /* skip first two directory entries: */
  530.   
  531.     rec = Get_Directory_Record (p_dir->volume,
  532.                         OBJ(p_dir,dir)->extent_loc_m,
  533.                     0);
  534.     if (!rec)
  535.       return 0;
  536.   
  537.     offset = rec->length;
  538.   
  539.     rec = Get_Directory_Record (p_dir->volume,
  540.                       OBJ(p_dir,dir)->extent_loc_m,
  541.                     offset);
  542.     if (!rec)
  543.       return 0;
  544.   
  545.     *p_offset = offset + rec->length;
  546.   }
  547.  
  548.   for (;;) {
  549.     if (OBJ(p_dir,dir)->data_length_m <= *p_offset)
  550.       return 0;
  551.  
  552.     rec = Get_Directory_Record (p_dir->volume,
  553.                       OBJ(p_dir,dir)->extent_loc_m,
  554.                     *p_offset);
  555.     if (!rec)
  556.       return 0;
  557.   
  558.     if (rec->length == 0)
  559.       /* go to next logical sector: */
  560.       *p_offset = (*p_offset & 0xfffff800) + 2048;
  561.     else
  562.       break;
  563.   }
  564.  
  565.   *p_offset += rec->length;
  566.  
  567.   if (p_dir->volume->protocol == PRO_ROCK &&
  568.       (len = Get_RR_File_Name (p_dir->volume, rec,
  569.                          p_info->name, sizeof (p_info->name))) > 0) {
  570.       p_info->name_length = len;
  571.   } else {
  572.     p_info->name_length = rec->file_id_length;
  573.     memcpy (p_info->name, rec->file_id, rec->file_id_length);
  574.   }
  575.   p_info->directory_f = rec->flags & 2;
  576.   p_info->file_length = rec->data_length_m;
  577.   p_info->date = Extract_Date (rec);
  578.   p_info->suppl_info = rec;
  579.  
  580.   return 1;
  581. }
  582.  
  583. /* Clone a "CDROM object info."
  584.  */
  585.  
  586. void *Iso_Clone_Obj_Info (void *p_info)
  587. {
  588.   t_iso_obj_info *info = (t_iso_obj_info *) p_info;
  589.   t_iso_obj_info *new;
  590.   
  591.   new = AllocMem (sizeof (t_iso_obj_info), MEMF_PUBLIC);
  592.   if (!new)
  593.     return NULL;
  594.  
  595.   memcpy (new, info, sizeof (t_iso_obj_info));
  596.  
  597.   new->dir = AllocMem (info->dir->length, MEMF_PUBLIC);
  598.   if (!new->dir) {
  599.     FreeMem (new, sizeof (t_iso_obj_info));
  600.     return NULL;
  601.   }
  602.   memcpy (new->dir, info->dir, info->dir->length);
  603.  
  604.   return new;
  605. }
  606.  
  607. /* Find parent directory.
  608.  */
  609.  
  610. CDROM_OBJ *Iso_Find_Parent (CDROM_OBJ *p_object)
  611. {
  612.   directory_record *dir;
  613.   
  614.   dir = Get_Directory_Record (p_object->volume,
  615.                     OBJ(p_object,dir)->extent_loc_m,
  616.                   0);
  617.   if (!dir)
  618.     return NULL;
  619.   
  620.   dir = Get_Directory_Record (p_object->volume,
  621.                   OBJ(p_object,dir)->extent_loc_m,
  622.                   dir->length);
  623.   if (!dir)
  624.     return NULL;
  625.  
  626.   return Iso_Create_Directory_Obj (p_object->volume, dir->extent_loc_m);
  627. }
  628.  
  629. /* Test if p_object is the root directory.
  630.  */
  631.  
  632. t_bool Iso_Is_Top_Level_Object (CDROM_OBJ *p_object)
  633. {
  634.   return p_object->directory_f &&
  635.          OBJ(p_object,dir)->extent_loc_m ==
  636.      VOL(p_object->volume,pvd).root.extent_loc_m;
  637. }
  638.  
  639. /* Test if two objects are equal.
  640.  */
  641.  
  642. t_bool Iso_Same_Objects (CDROM_OBJ *p_obj1, CDROM_OBJ *p_obj2)
  643. {
  644.   return (OBJ(p_obj1,dir)->extent_loc_m ==
  645.       OBJ(p_obj2,dir)->extent_loc_m);
  646. }
  647.  
  648. /*
  649.  * Convert p_num digits into an integer value:
  650.  */
  651.  
  652. int Digs_To_Int (char *p_digits, int p_num)
  653. {
  654.   int result = 0;
  655.   int i;
  656.   
  657.   for (i=0; i<p_num; i++)
  658.     result = result * 10 + p_digits[i] - '0';
  659.     
  660.   return result;
  661. }
  662.  
  663. /*
  664.  * Return volume creation date as number of seconds since 1-Jan-1978:
  665.  */
  666.  
  667. t_ulong Iso_Creation_Date (VOLUME *p_volume)
  668. {
  669.   struct ClockData ClockData;
  670.   char *dt = VOL(p_volume,pvd).vol_creation;
  671.  
  672.   ClockData.sec   = Digs_To_Int (dt+12, 2);
  673.   ClockData.min      = Digs_To_Int (dt+10, 2);
  674.   ClockData.hour  = Digs_To_Int (dt+8, 2);
  675.   ClockData.mday  = Digs_To_Int (dt+6, 2);
  676.   ClockData.wday  = 0; /* is ignored by CheckDate() and Date2Amiga() */
  677.   ClockData.month = Digs_To_Int (dt+4, 2);
  678.   ClockData.year  = Digs_To_Int (dt, 4);
  679.  
  680.   if (CheckDate (&ClockData))
  681.     return Date2Amiga (&ClockData);
  682.   else
  683.     return 0;
  684. }
  685.  
  686. t_ulong Iso_Volume_Size (VOLUME *p_volume)
  687. {
  688.   return VOL(p_volume,pvd).space_size_m;
  689. }
  690.  
  691. t_ulong Iso_Block_Size (VOLUME *p_volume)
  692. {
  693.   return VOL(p_volume,pvd).block_size_m;
  694. }
  695.  
  696. void Iso_Volume_ID (VOLUME *p_volume, char *p_buffer, int p_buf_length)
  697. {
  698.   char *iso_name = VOL(p_volume,pvd).volume_id;
  699.   int iso_len;
  700.   int len;
  701.  
  702.   for (iso_len = 32; iso_len; iso_len--) {
  703.     if (iso_name[iso_len-1] != ' ')
  704.       break;
  705.   }
  706.  
  707.   len = (iso_len > p_buf_length-1) ? p_buf_length-1 : iso_len;
  708.   if (len > 0)
  709.     memcpy (p_buffer, iso_name, len);
  710.   p_buffer[len] = 0;
  711. }
  712.  
  713. t_ulong Iso_Location (CDROM_OBJ *p_object)
  714. {
  715.   return OBJ(p_object,dir)->extent_loc_m;
  716. }
  717.  
  718. t_ulong Iso_File_Length (CDROM_OBJ *p_obj)
  719. {
  720.   return OBJ(p_obj,dir)->data_length_m;
  721. }
  722.  
  723. t_handler g_iso_handler = {
  724.   Iso_Close_Vol_Info,
  725.   Iso_Open_Top_Level_Directory,
  726.   Iso_Open_Obj_In_Directory,
  727.   Iso_Find_Parent,
  728.   Iso_Close_Obj,
  729.   Iso_Read_From_File,
  730.   Iso_CDROM_Info,
  731.   Iso_Examine_Next,
  732.   Iso_Clone_Obj_Info,
  733.   Iso_Is_Top_Level_Object,
  734.   Iso_Same_Objects,
  735.   Iso_Creation_Date,
  736.   Iso_Volume_Size,
  737.   Iso_Volume_ID,
  738.   Iso_Location,
  739.   Iso_File_Length,
  740.   Iso_Block_Size
  741. };
  742.  
  743. t_handler g_rr_handler = {
  744.   Iso_Close_Vol_Info,
  745.   Iso_Open_Top_Level_Directory,
  746.   Iso_Open_Obj_In_Directory,
  747.   Iso_Find_Parent,
  748.   Iso_Close_Obj,
  749.   Iso_Read_From_File,
  750.   Iso_CDROM_Info,
  751.   Iso_Examine_Next,
  752.   Iso_Clone_Obj_Info,
  753.   Iso_Is_Top_Level_Object,
  754.   Iso_Same_Objects,
  755.   Iso_Creation_Date,
  756.   Iso_Volume_Size,
  757.   Iso_Volume_ID,
  758.   Iso_Location,
  759.   Iso_File_Length,
  760.   Iso_Block_Size
  761. };
  762.  
  763.